package com.max.common.task;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 
 * 项目名称:max-project-graphics
 * 文件名称:BaseTimerTask.java
 * 文件描述:
 * 创建人员:chenyibo
 * 创建时间:2013-1-29 下午03:07:12
 * 修改人员:chenyibo
 * 修改时间:2013-1-29 下午03:07:12
 * 修改备注:
 * @version V1.0
 */
public class BaseTimerTask extends TimerTask
{

	private static Log log = LogFactory.getLog("task");
	
    /**
     * 实际具体执行的任务对象
     */
    private Runnable taskObj;

    // 任务所属的Timer
    Timer timer;

    /**
     * 任务显示名称
     */
    private String taskName = "";

    /**
    * 任务类类全名
    */
    private String className = "";

    /**
    * 任务运行（计划）标识
    */
    private boolean runFlag;

    /**
    * 任务独立运行（在线程中）标识
    */
    private boolean separateFlag;

    /**
    * 任务重复运行标识
    */
    private boolean repeatFlag;

    /**
     * 任务被监控标识
     */
    private boolean monitorFlag;

    /**
     * 任务运行在后台标识
     */
    private boolean daemonFlag;

    /**
     * 具体任务是否正在执行中标识
     */
    private boolean executingFlag = false;

    /**
     * 任务是否被删除（cancel）标识
     */
    private boolean cancelFlag;

    /**
     * 任务运行的开始时间
     */
    private Date startTime = new Date();

    /**
     * 任务运行的间隔时间（单位：秒）
     */
    private long intervalTime = 0;

    /**
     * 任务运行的最可长运行时间（单位：秒）
     */
    private long maxRunTime = 0;

    /**
     * 具体任务执行的最后一次开始时间
     */
    private long lastRunTime = 0L;

    
    /**
     * 初始化任务信息
     * 从xml预定义的格式中获取任务参数配置项，初始化任务配置文件中的任务
     * @param aTaskMap  xml配置文件中任务的参数map
     * @return  初始化设置任务
     */
    public synchronized boolean initFrmXML(Map aTaskMap)
    {
        //若参数为null或为空，则返回false
        if (aTaskMap == null || aTaskMap.isEmpty() )
        {
            log.info("init xml file failed!file name null!");
            return false;
        }

        //验证参数是否和预定义的是否完全一致
        //（调用者AsyTaskManager中已经验证了，故此处省去）

        //读取taskmap中监控标识
        String monitorFlag =  ((String)aTaskMap.get("monitor-flag") ).trim();

        //如果需要监控则创建一个监控任务对象，否则为普通类对象
        if (Boolean.valueOf(monitorFlag).booleanValue())
        {
            this.setMonitorFlag(true);

            //初始化最长运行限制时间(只有监控类必须有)
            long maxRunTime = 0;
            try
            {
                maxRunTime = Long.parseLong(((String)aTaskMap.get("max-run-time")).trim());
            }
            catch(java.lang.NumberFormatException e)
            {
            	e.printStackTrace();
            	log.info("init xml file failed!"+e.getMessage());
                return false;
            }
            this.setMaxRunTime(maxRunTime);
        }
        else //否则为普通类对象
        {
            this.setMonitorFlag(false);
        }

        //初始化具体任务对象:判断className的类是否存在，
        //若存在，判断有没有实现run()方法，若无，返回false;
        String className = (String)aTaskMap.get("class-name");
        if (className == null || "".equals(className))
        {
            return false;
        }

        try
        {
            //新建className的新对象
            Object obj = Class.forName(className).newInstance();

            //判断有没有实现Runnable接口
            if (!(Runnable.class).isInstance(obj))
            {
                log.info("init xml file failed!Runnable not found exception " + className);
                return false;
            }

            //设置任务对象和类全名
            this.setTaskObj((Runnable)obj);
            this.setClassName(className);
        }
        catch (ClassNotFoundException e)
        {
        	e.printStackTrace();
            log.info("init xml file failed!"+e.getMessage());
            return false;
        }
        catch (InstantiationException e)
        {
        	e.printStackTrace();
        	log.info("init xml file failed!"+e.getMessage());
            return false;
        }
        catch (IllegalAccessException e)
        {
        	e.printStackTrace();
        	log.info("init xml file failed!"+e.getMessage());
            return false;
        }

        //初始化开始运行时间
        String startDateTime = (String)aTaskMap.get("start-datetime");
        SimpleDateFormat sdf  = new SimpleDateFormat();
        sdf.applyPattern("yyyy-MM-dd HH:mm:ss");
        try
        {
            Date tempDate = sdf.parse(startDateTime);
            this.setStartTime(tempDate);
        }
        catch (java.text.ParseException e)
        {
        	e.printStackTrace();
        	log.info("init xml file failed!"+e.getMessage());
            return false;
        }

        //初始化剩余的参数:
        String displayName = (String)aTaskMap.get("display-name");
        this.setTaskName(displayName);

        String separateFlag = (String)aTaskMap.get("separate-flag");
        this.setSeparateFlag(Boolean.valueOf(separateFlag).booleanValue());

        String runFlag = (String)aTaskMap.get("run-flag");
        this.setRunFlag( Boolean.valueOf(runFlag).booleanValue());

        String daemonFlag = (String)aTaskMap.get("daemon-flag");
        this.setDaemonFlag( Boolean.valueOf(daemonFlag).booleanValue());

        String repeatFlag = (String)aTaskMap.get("repeat-flag");
        this.setRepeatFlag( Boolean.valueOf(repeatFlag).booleanValue());

        //如果该任务是需要循环运行，就读取初始化间隔时间
        if (this.isRepeat())
        {
            long intervalTime = 0;
            try
            {
                intervalTime = Long.parseLong(((String) aTaskMap.get("interval-time")).trim());
            }
            catch (java.lang.NumberFormatException e)
            {
            	e.printStackTrace();
            	log.info("init xml file failed!"+e.getMessage());
                return false;
            }

            if (intervalTime<1)
            {
                log.info("init xml file failed!Interval time invalid");
                return false;
            }

            this.setIntervalTime(intervalTime);
        }

        return true;
    }

    public void run()
    {
        // 任务可以允许运行并且具体任务不是正在执行中
        if ( this.isRun()  && !this.isExecuting() )
        {
        	long time = System.currentTimeMillis();
        	log.info("Start excuting task " + this.getTaskName() + "...");

            //记录实际运行时间
            this.lastRunTime = System.currentTimeMillis();

            this.setExecutingFlag(true);
            try
            {
                this.getTaskObj().run();
            }
            catch (Exception e)
            {
            	e.printStackTrace();
                log.info("Start excuting task catch an exception:" + e.getMessage());
            }
            this.setExecutingFlag(false);

            log.info("Start excuting task " + this.getTaskName() + " complete!cost " + (System.currentTimeMillis()-time) + " ms!");
        }
    }
    
    /**
     * 删除任务 并置删除标识为true
     * @return boolean
     */
    public synchronized boolean cancel()
    {
        boolean result = false;

        if (!this.cancelFlag)
            result = super.cancel();

        this.cancelFlag = true;
        this.timer = null; // wuwei41571 2007-07-02

        return result;
    }

    /**
     * 拷贝自身对象各项参数封装成新对象，返回拷贝后的对
     * @return  新封装的BaseTimerTask对象
     */
    public synchronized BaseTimerTask copy()
    {

        //创建一个新对象，把对象的参数复制到新对象中
        BaseTimerTask newbtt = new BaseTimerTask();

        newbtt.setClassName(this.className);
        newbtt.setDaemonFlag(this.daemonFlag);
        newbtt.setIntervalTime(this.intervalTime);
        // newbtt.setLastRunTime(this.lastRunTime);
        //newbtt.setExecutingFlag(this.executingFlag);
        newbtt.setMaxRunTime(this.maxRunTime);
        newbtt.setMonitorFlag(this.monitorFlag);
        newbtt.setRepeatFlag(this.repeatFlag);
        newbtt.setRunFlag(this.runFlag);
        newbtt.setSeparateFlag(this.separateFlag);
        newbtt.setStartTime(this.startTime);
        newbtt.setTaskName(this.taskName);
        newbtt.setTaskObj(this.taskObj);
        newbtt.timer = this.timer;

        return newbtt;
    }

    /**
     * 获取实际的具体任务对象
     * @return taskObj 实际的具体任务对象
     */
    public Runnable getTaskObj()
    {
        return taskObj;
    }

    /**
     * 设置执行具体任务的任务对象
     * @param aTaskObj  任务对象
     */
    public void setTaskObj(Runnable aTaskObj)
    {
        this.taskObj = aTaskObj;
    }

    /**
     * 获取任务类全名
     * @return className  任务类全名
     */
    public String getClassName()
    {
        return className;
    }

    /**
     * 设置任务类全名
     * @param aClassName 任务类全名
     */
    public void setClassName(String aClassName)
    {
        this.className = aClassName;
    }

    /**
     * 获取任务显示名称
     * @return taskName 任务显示名称
     */
    public String getTaskName()
    {
        return taskName;
    }

    /**
     * 设置任务显示名称
     * @param aTaskName 任务显示名称
     */
    public void setTaskName(String aTaskName)
    {
        this.taskName = aTaskName;
    }

    /**
     * 获取任务开始时间
     * @return 任务开始时间
     */
    public Date getStartTime()
    {
        return startTime;
    }

    /**
     * 设置任务开始时间
     * @param aStartTime  开始时间
     */
    public void setStartTime(Date aStartTime)
    {
        this.startTime = aStartTime;
    }

    /**
     * 获取任务运行间隔时间
     * @return 任务运行间隔时间
     */
    public long getIntervalTime()
    {
        return intervalTime;
    }

    /**
     * 设置任务运行间隔时间
     * @param aIntervalTime  运行间隔时间
     */
    public void setIntervalTime(long aIntervalTime)
    {
        //是否要判定间隔时间大于最大运行时间？
        this.intervalTime = aIntervalTime;
    }

    /**
     * 获取任务的最长运行时间（单位：分钟）
     * @return 任务的最长运行时间 （单位：分钟）
     */
    public long getMaxRunTime()
    {
        return this.maxRunTime;
    }

    /**
     * 设置任务的最长运行时间（单位：分钟）
     * @param aMaxRunTime 任务的最长运行时间   （单位：分钟)
     */
    public void setMaxRunTime(long aMaxRunTime)
    {
        //是否要判定间隔时间大于最大运行时间？
        this.maxRunTime = aMaxRunTime;
    }

    /**
     * 获取任务的最后一次开始运行时间
     * @return 最后一次开始运行时间
     */
    public long getLastRunTime()
    {
        return this.lastRunTime;
    }

    /**
     * 设置运行标识
     * @param aRunFlag 运行标识
     */
    public void setRunFlag(boolean aRunFlag)
    {
        this.runFlag = aRunFlag;
    }

    /**
     *  是否在运行中
     * @return boolean
     */
    public boolean isRun()
    {
        return this.runFlag;
    }

    /**
     * 设置监控标识
     * @param aMonitorFlag 监控标识
     */
    public void setMonitorFlag(boolean aMonitorFlag)
    {
        this.monitorFlag = aMonitorFlag;
    }

    /**
     *  是否要监控
     * @return boolean
     */
    public boolean isMonitor()
     {
         return monitorFlag;
     }

     /**
      * 设置是否要在后台运行（守护线程中）
      * @param aDaemonFlag 后台运行标识
      */
     public void setDaemonFlag(boolean aDaemonFlag)
     {
         this.daemonFlag = aDaemonFlag;
     }

     /**
      *  是否在后台运行（守护线程内）
      * @return boolean
      */
     public boolean isDaemon()
     {
         return daemonFlag;
     }

     /**
      * 设置是否要独立独立
      * @param aSeparateFlag 独立运行标识
      */
     public void setSeparateFlag(boolean aSeparateFlag)
     {
         this.separateFlag = aSeparateFlag;
     }

    /**
     * 是否在独立线程内(Timer对象)
     * @return boolean
     */
    public boolean isSeparate()
    {
        return separateFlag;
    }

    /**
     * 设置重复运行
     * @param aRepeatFlag 重复运行标识
     */
    public void setRepeatFlag(boolean aRepeatFlag)
    {
        this.repeatFlag = aRepeatFlag;
    }

    /**
     * 是否要重复运行
     * @return boolean
     */
    public boolean isRepeat()
    {
        return repeatFlag;
    }

    /**
     * 设置实际具体任务正在运行
     * @param aExecutingFlag 实际具体任务正在运行标识
     */
    public void setExecutingFlag(boolean aExecutingFlag)
    {
        this.executingFlag = aExecutingFlag;
    }

    /**
     * 实际具体任务是否正在运行当中
     * @return boolean
     */
    public boolean isExecuting()
    {
        return executingFlag;
    }

    /**
     * 任务是否被删除
     * @return boolean
     */
    public boolean isCancel()
    {
        return this.cancelFlag;
    }
}
